home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / file / managers / git-4.3 / git-4 / git-4.3.7 / src / gitview.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-08  |  16.6 KB  |  714 lines

  1. /* gitview.c -- a hex/ascii file viewer. There are hops that this will become
  2.    a hex/ascii file editor one day ... */
  3.  
  4. /* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
  5.  
  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2, or (at your option)
  9.    any later version.
  10.  
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /* Written by Tudor Hulubei and Andrei Pitis.  */
  21.  
  22.  
  23. #ifdef HAVE_CONFIG_H
  24. #include <config.h>
  25. #endif
  26.  
  27. #include <stdio.h>
  28.  
  29. #ifdef HAVE_STDLIB_H
  30. #include <stdlib.h>
  31. #else /* !HAVE_STDLIB_H */
  32. #include "ansi_stdlib.h"
  33. #endif /* !HAVE_STDLIB_H */
  34.  
  35. #include <sys/types.h>
  36. #include <limits.h>
  37. #include "file.h"
  38. #include <fcntl.h>
  39. #include <signal.h>
  40. #include <ctype.h>
  41.  
  42. #ifdef HAVE_UNISTD_H
  43. #include <unistd.h>
  44. #endif /* HAVE_UNISTD_H */
  45.  
  46. #include "stdc.h"
  47. #include "xstring.h"
  48. #include "xmalloc.h"
  49. #include "xio.h"
  50. #include "window.h"
  51. #include "configure.h"
  52. #include "tty.h"
  53. #include "misc.h"
  54. #include "tilde.h"
  55.  
  56.  
  57. #define MAX_KEYS                        2048
  58.  
  59. #define BUILTIN_OPERATIONS              11
  60.  
  61.  
  62. #define BUILTIN_previous_line           -1
  63. #define BUILTIN_next_line               -2
  64. #define BUILTIN_scroll_down             -3
  65. #define BUILTIN_scroll_up               -4
  66. #define BUILTIN_beginning_of_file       -5
  67. #define BUILTIN_end_of_file             -6
  68. #define BUILTIN_refresh                 -7
  69. #define BUILTIN_exit                    -8
  70. #define BUILTIN_hard_refresh            -9
  71. #define BUILTIN_backspace               -10
  72. #define BUILTIN_action                  -11
  73.  
  74.  
  75. #define MAX_BUILTIN_NAME                20
  76.  
  77. char built_in[BUILTIN_OPERATIONS][MAX_BUILTIN_NAME] =
  78. {
  79.     "previous-line",
  80.     "next-line",
  81.     "scroll-down",
  82.     "scroll-up",
  83.     "beginning-of-file",
  84.     "end-of-file",
  85.     "refresh",
  86.     "exit",
  87.     "hard-refresh",
  88.     "backspace",
  89.     "action",
  90. };
  91.  
  92.  
  93. int SCREEN_X;
  94. int SCREEN_Y;
  95.  
  96. #define VIEWER_FIELDS 12
  97.  
  98. static char *ViewerFields[VIEWER_FIELDS] =
  99. {
  100.     "TitleForeground",
  101.     "TitleBackground",
  102.     "TitleBrightness",
  103.     "HeaderForeground",
  104.     "HeaderBackground",
  105.     "HeaderBrightness",
  106.     "ScreenForeground",
  107.     "ScreenBackground",
  108.     "ScreenBrightness",
  109.     "StatusForeground",
  110.     "StatusBackground",
  111.     "StatusBrightness"
  112. };
  113.  
  114. #ifdef HAVE_LINUX
  115. static int ViewerColors[VIEWER_FIELDS] = 
  116. {
  117.     CYAN, BLUE, ON, CYAN, RED, ON, BLACK, CYAN, OFF, CYAN, BLUE, ON
  118. };
  119. #else   /* !HAVE_LINUX */
  120. static int ViewerColors[VIEWER_FIELDS] = 
  121. {
  122.     BLACK, WHITE, OFF, WHITE, BLACK, ON, WHITE, BLACK, OFF, BLACK, WHITE, OFF
  123. };
  124. #endif  /* !HAVE_LINUX */
  125.  
  126. #define TitleForeground                 ViewerColors[0]
  127. #define TitleBackground                 ViewerColors[1]
  128. #define TitleBrightness                 ViewerColors[2]
  129. #define HeaderForeground                ViewerColors[3]
  130. #define HeaderBackground                ViewerColors[4]
  131. #define HeaderBrightness                ViewerColors[5]
  132. #define ScreenForeground                ViewerColors[6]
  133. #define ScreenBackground                ViewerColors[7]
  134. #define ScreenBrightness                ViewerColors[8]
  135. #define StatusForeground                ViewerColors[9]
  136. #define StatusBackground                ViewerColors[10]
  137. #define StatusBrightness                ViewerColors[11]
  138.  
  139.  
  140. #ifdef HAVE_LINUX
  141. int AnsiColorSequences = ON;
  142. #else   /* !HAVE_LINUX */
  143. int AnsiColorSequences = OFF;
  144. #endif  /* !HAVE_LINUX */
  145.  
  146.  
  147.  
  148. #ifdef STAT_MACROS_BROKEN
  149. #ifdef S_IFREG
  150. #undef S_IFREG
  151. #endif
  152. #ifdef S_IFBLK
  153. #undef S_IFBLK
  154. #endif
  155. #endif /* STAT_MACROS_BROKEN */
  156.  
  157.  
  158. #ifndef S_IFREG
  159. #define S_IFREG         0100000
  160. #endif
  161.  
  162. #ifndef S_IFBLK
  163. #define S_IFBLK         0060000
  164. #endif
  165.  
  166. #ifndef S_ISREG
  167. #define S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)
  168. #endif
  169.  
  170. #ifndef S_ISBLK
  171. #define S_ISBLK(m)      (((m) & S_IFMT) == S_IFBLK)
  172. #endif
  173.  
  174. /* Finally ... :-( */
  175.  
  176.  
  177. char *home;
  178. pid_t pid;
  179. char *program;
  180. char *tty_name;
  181. size_t  tty_name_len;
  182. char *header_text;
  183. int  UseLastScreenChar;
  184. char *global_buf = NULL;
  185. char cSection[]  = "[GITVIEW-Color]";
  186. char bwSection[] = "[GITVIEW-Monochrome]";
  187. int handle, regular_file;
  188. int current_line, lines;
  189. window_t *title_win, *header_win, *screen_win, *status_win;
  190. #ifdef HAVE_GCC
  191. static char title_text[] = " "PRODUCT" "VERSION" - Hex/Ascii File Viewer";
  192. #else
  193. static char title_text[] = " GNU Interactive Tools 4.3.7 - Hex/Ascii File Viewer";
  194. #endif /* !HAVE_GCC */
  195. static char *GitViewModeHelp;
  196. static char info_txt[] =
  197.     "   Offset    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F        \
  198. Ascii       ";
  199. static char line_txt[]    =
  200.     "  ------------------------------------------------------------------\
  201. ----------  ";
  202. static char seek_txt[]    = "  Seek at: ";
  203.  
  204.  
  205. int
  206. filelength()
  207. {
  208.     int tmp, length;
  209.  
  210.     if (!regular_file)
  211.         return 0x7FFFFFFF;
  212.  
  213.     tmp    = lseek(handle, 0, SEEK_CUR);
  214.     length = lseek(handle, 0, SEEK_END);
  215.     lseek(handle, tmp, SEEK_SET);
  216.     return length;
  217. }
  218.  
  219.  
  220. void
  221. settitle()
  222. {
  223.     memset(global_buf, ' ', SCREEN_X);
  224.     memcpy(global_buf, title_text, strlen(title_text));
  225.  
  226.     tty_colors(TitleBrightness, TitleForeground, TitleBackground);
  227.  
  228.     window_cursormove_notify(title_win, 0, 0);
  229.     window_write(global_buf, SCREEN_X);
  230. }
  231.  
  232.  
  233. void
  234. setheader()
  235. {
  236.     memset(global_buf, ' ', SCREEN_X);
  237.     memcpy(global_buf, header_text, min(strlen(header_text), SCREEN_X));
  238.  
  239.     tty_colors(HeaderBrightness, HeaderForeground, HeaderBackground);
  240.  
  241.     window_cursormove_notify(header_win, 0, 0);
  242.     window_write(global_buf, SCREEN_X);
  243. }
  244.  
  245.  
  246. void
  247. setstatus()
  248. {
  249.     memset(global_buf, ' ', SCREEN_X);
  250.     memcpy(global_buf, GitViewModeHelp, strlen(GitViewModeHelp));
  251.  
  252.     tty_colors(StatusBrightness, StatusForeground, StatusBackground);
  253.  
  254.     window_cursormove_notify(status_win, 0, 0);
  255.  
  256.     if (UseLastScreenChar)
  257.         window_write(global_buf, SCREEN_X);
  258.     else
  259.         window_write(global_buf, SCREEN_X - 1);
  260. }
  261.  
  262.  
  263. char
  264. char_to_print(c)
  265.     char c;
  266. {
  267.     return is_print(c) ? c : '.';
  268. }
  269.  
  270.  
  271. void
  272. update_line(line)
  273.     int line;
  274. {
  275.     int r;
  276.     unsigned char ln[16];
  277.  
  278.     memset(ln, 0, 16);
  279.     memset(global_buf, ' ', SCREEN_X);
  280.     lseek(handle, line * 16, SEEK_SET);
  281.  
  282.     if ((r = read(handle, ln, 16)))
  283.         sprintf(global_buf, "  %07X0   %02X %02X %02X %02X %02X %02X %02X\
  284.  %02X %02X %02X %02X %02X %02X %02X %02X %02X  %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c  ",
  285.                 line,
  286.                 ln[0], ln[1], ln[2],  ln[3],  ln[4],  ln[5],  ln[6],  ln[7],
  287.                 ln[8], ln[9], ln[10], ln[11], ln[12], ln[13], ln[14], ln[15],
  288.                 char_to_print(ln[0]),  char_to_print(ln[1]),
  289.                 char_to_print(ln[2]),  char_to_print(ln[3]),
  290.                 char_to_print(ln[4]),  char_to_print(ln[5]),
  291.                 char_to_print(ln[6]),  char_to_print(ln[7]),
  292.                 char_to_print(ln[8]),  char_to_print(ln[9]),
  293.                 char_to_print(ln[10]), char_to_print(ln[11]),
  294.                 char_to_print(ln[12]), char_to_print(ln[13]),
  295.                 char_to_print(ln[14]), char_to_print(ln[15]));
  296.  
  297.     if (r < 0)
  298.         r = 0;
  299.  
  300.     if (r != 16)
  301.     {
  302.         memset(global_buf + 13 + r * 3, ' ', (16 - r) * 3 - 1);
  303.         memset(global_buf + 13 + 16 * 3 - 1 + 2 + r, ' ', 16 - r + 2);
  304.     }
  305.  
  306.     window_write((char *)global_buf, SCREEN_X);
  307. }
  308.  
  309.  
  310. void
  311. update_all()
  312. {
  313.     int i;
  314.     
  315.     tty_cursor(OFF);
  316.  
  317.     tty_colors(ScreenBrightness, ScreenForeground, ScreenBackground);
  318.  
  319.     for (i = current_line; i < current_line + 16; i++)
  320.     {
  321.         window_cursormove_notify(screen_win, 3 + i - current_line, 0);
  322.         update_line(i);
  323.     }
  324.  
  325.     tty_cursor(ON);
  326. }
  327.  
  328.  
  329. void
  330. clean_up()
  331. {
  332.     tty_exit();
  333. }
  334.  
  335.  
  336. void
  337. fatal(postmsg)
  338.     char *postmsg;
  339. {
  340.     clean_up();
  341.     fprintf(stderr, "%s: fatal error: %s.\n", program, postmsg);
  342.     exit(1);
  343. }
  344.  
  345.  
  346. RETSIGTYPE
  347. panic(signum)
  348.     int signum;
  349. {
  350.     fatal_signal(signum);
  351. }
  352.  
  353.  
  354. int
  355. read_keys(keys)
  356.     int keys;
  357. {
  358.     char *contents;
  359.     char key_seq[80];
  360.     int i, j, need_convertion;
  361.  
  362.  
  363.     for (i = keys; i < MAX_KEYS; i++)
  364.     {
  365.         configuration_getvarinfo(key_seq, &contents, 1, NO_SEEK);
  366.  
  367.         if (*key_seq == 0)
  368.             break;
  369.  
  370.         if (*key_seq != '^')
  371.         {
  372.             char *key_seq_ptr = tty_get_symbol_key_seq(key_seq);
  373.  
  374.             if (!(need_convertion = key_seq_ptr == NULL))
  375.                 strcpy(key_seq, key_seq_ptr);
  376.         }
  377.         else
  378.             need_convertion = 1;
  379.  
  380.         if (contents == NULL) continue;
  381.  
  382.         for (j = 0; j < BUILTIN_OPERATIONS; j++)
  383.             if (strcmp(contents, built_in[j]) == 0)
  384.                 break;
  385.  
  386.         if (j < BUILTIN_OPERATIONS)
  387.         {
  388.             if (!need_convertion || tty_key_convert(key_seq))
  389.                 tty_key_list_insert(key_seq, (void *)(long)-(j + 1));
  390.         }
  391.         else
  392.             fprintf(stderr, "%s: invalid built-in operation: %s.\n",
  393.                     program, contents);
  394.     }
  395.  
  396.     return i;
  397. }
  398.  
  399.  
  400. int
  401. main(argc, argv)
  402.     int argc;
  403.     char *argv[];
  404. {
  405.     char c;
  406.     long key;
  407.     struct stat s;
  408.     tty_key_t *ks;
  409.     char offset[16];
  410.     int cnt = 0, size;
  411.     int keys, repeat_count, first_time = 1, need_update;
  412.  
  413.  
  414.     program = argv[0];
  415.  
  416.     home = getenv("HOME");
  417.     if (home == NULL)
  418.         home = ".";
  419.  
  420.     get_tty_name();
  421.     get_login_name();
  422.  
  423.     tty_name_len = strlen(tty_name);
  424.  
  425.     tty_get_capabilities();
  426.     tty_kbdinit(TTY_RESTRICTED_INPUT);
  427.  
  428.     signal(SIGTERM, panic);
  429.     signal(SIGINT , panic);
  430.     signal(SIGQUIT, panic);
  431.     signal(SIGSEGV, panic);
  432.     signal(SIGHUP,  panic);
  433.  
  434.     signal(SIGILL,  SIG_IGN);
  435.     signal(SIGTRAP, SIG_IGN);
  436.     signal(SIGABRT, SIG_IGN);
  437.     signal(SIGUSR1, SIG_IGN);
  438.     signal(SIGUSR2, SIG_IGN);
  439.     signal(SIGTSTP, SIG_IGN);
  440.     signal(SIGCONT, SIG_IGN);
  441.     signal(SIGALRM, SIG_IGN);
  442.     signal(SIGPIPE, SIG_IGN);
  443.     signal(SIGFPE,  SIG_IGN);
  444.  
  445.     if (argc != 2)
  446.     {
  447.         fprintf(stderr, "usage: gitview filename\n");
  448.         exit(1);
  449.     }
  450.  
  451.     xstat(argv[1], &s);
  452.  
  453.     if (!(S_ISREG(s.st_mode) || S_ISBLK(s.st_mode)))
  454.     {
  455.         fprintf(stderr, "%s: %s is neither regular file nor block device.\n",
  456.                 program, argv[1]);
  457.         exit(1);
  458.     }
  459.  
  460.     handle = open(argv[1], O_RDONLY);
  461.  
  462.     if (handle == -1)
  463.     {
  464.         fprintf(stderr, "%s: cannot open file %s.\n", program, argv[1]);
  465.         exit(1);
  466.     }
  467.  
  468.     regular_file = S_ISREG(s.st_mode);
  469.  
  470.     common_configuration_init();
  471.     use_section("[GITVIEW-Keys]");
  472.     keys = read_keys(0);
  473.     configuration_end();
  474.  
  475.     specific_configuration_init();
  476.  
  477.     tty_get_exit_colors();
  478.  
  479.     use_section("[Setup]");
  480.  
  481.     AnsiColorSequences = get_flag_var("AnsiColorSequences", OFF);
  482.  
  483.     UseLastScreenChar  = get_flag_var("UseLastScreenChar", OFF);
  484.  
  485.  
  486.     use_section("[GITVIEW-Setup]");
  487.  
  488.     GitViewModeHelp = get_string_var("GitViewModeHelp", "");
  489.  
  490.     use_section(AnsiColorSequences ? cSection : bwSection);
  491.  
  492.     get_colorset_var(ViewerColors, ViewerFields, VIEWER_FIELDS);
  493.  
  494.  
  495.     use_section("[GITVIEW-Keys]");
  496.  
  497.     keys = read_keys(keys);
  498.  
  499.     if (keys == MAX_KEYS)
  500.         fprintf(stderr, "%s: too many key sequences; only %d are allowed.\n",
  501.                 program, MAX_KEYS);
  502.  
  503.     configuration_end();
  504.  
  505.     tty_get_size(&SCREEN_X, &SCREEN_Y);
  506.     tty_startup();
  507.  
  508.     if (SCREEN_Y < 24)
  509.     {
  510.         SCREEN_Y = 24;
  511.         fprintf(stderr, "%s: WARNING: can't use less than 24 columns.\n",
  512.                 program);
  513.     }
  514.  
  515.     global_buf  = xmalloc(SCREEN_X + 1);
  516.  
  517.     header_text = xmalloc(strlen(argv[1]) + 10);
  518.     sprintf(header_text, " File: %s", argv[1]);
  519.  
  520.     title_win  = window_init(0, 0,            1,            SCREEN_X);
  521.     header_win = window_init(0, 1,            1,            SCREEN_X);
  522.     screen_win = window_init(0, 2,            SCREEN_Y - 2, SCREEN_X);
  523.     status_win = window_init(0, SCREEN_Y - 1, 1,            SCREEN_X);
  524.  
  525.     tty_set_mode(TTY_NONCANONIC);
  526.  
  527.     offset[cnt]  = 0;
  528.     current_line = 0;
  529.  
  530.  
  531. restart:
  532.  
  533.     if (first_time)
  534.     {
  535.         tty_colors(ScreenBrightness, ScreenForeground, ScreenBackground);
  536.         tty_clear();
  537.         first_time = 0;
  538.     }
  539.  
  540.     settitle();
  541.     setstatus();
  542.     setheader();
  543.  
  544.     tty_colors(ScreenBrightness, ScreenForeground, ScreenBackground);
  545.  
  546.     window_cursormove_notify(screen_win, 1, 0);
  547.     window_write(info_txt, sizeof(info_txt) - 1);
  548.     window_cursormove_notify(screen_win, 2, 0);
  549.     window_write(line_txt, sizeof(line_txt) - 1);
  550.  
  551.     size = filelength();
  552.     lines = size / 16 + (size % 16 ? 1 : 0);
  553.  
  554.     current_line = min(current_line, (lines / 16) * 16);
  555.  
  556.     update_all();
  557.  
  558.     window_cursormove_notify(screen_win, 20, 0);
  559.     window_write(seek_txt, sizeof(seek_txt) - 1);
  560.     window_cursormove_notify(screen_win, 20, sizeof(seek_txt) - 1);
  561.     window_write(offset, cnt);
  562.  
  563.     window_cursormove(screen_win, 20, sizeof(seek_txt) - 1 + cnt);
  564.  
  565.     while (1)
  566.     {
  567.         ks  = tty_get_key(&repeat_count);
  568.         key = (long)ks->aux_data;
  569.  
  570.         if (key == 0)
  571.             key = ks->key_seq[0];
  572.  
  573.         size = filelength();
  574.         lines = size / 16 + (size % 16 ? 1 : 0);
  575.  
  576.         switch (key)
  577.         {
  578.             case key_INTERRUPT:
  579.                 goto end;
  580.  
  581.             case BUILTIN_previous_line:
  582.  
  583.                 need_update = 0;
  584.  
  585.                 while (repeat_count--)
  586.                 {
  587.                     if (current_line == 0)
  588.                         break;
  589.                     current_line--, need_update = 1;
  590.                 }
  591.  
  592.                 if (need_update)
  593.                     update_all();
  594.                 break;
  595.  
  596.             case BUILTIN_next_line:
  597.  
  598.                 need_update = 0;
  599.  
  600.                 while (repeat_count--)
  601.                 {
  602.                     if (current_line >= lines - 16)
  603.                         break;
  604.                     current_line++, need_update = 1;
  605.                 }
  606.  
  607.                 if (need_update)
  608.                     update_all();
  609.                 break;
  610.  
  611.             case BUILTIN_scroll_down:
  612.  
  613.                 if (current_line == 0)
  614.                     break;
  615.  
  616.                 current_line = max(0, current_line - 16);
  617.                 update_all();
  618.                 break;
  619.  
  620.             case BUILTIN_scroll_up:
  621.  
  622.                 if (current_line >= lines - 16)
  623.                     break;
  624.  
  625.                 current_line += 16;
  626.                 update_all();
  627.                 break;
  628.  
  629.             case BUILTIN_beginning_of_file:
  630.  
  631.                 if (current_line)
  632.                 {
  633.                     current_line = 0;
  634.                     update_all();
  635.                 }
  636.                 break;
  637.  
  638.             case BUILTIN_end_of_file:
  639.  
  640.                 if (regular_file && current_line < lines - 16)
  641.                 {
  642.                     current_line = lines - 16;
  643.                     update_all();
  644.                 }
  645.                 break;
  646.  
  647.             case BUILTIN_hard_refresh: 
  648.  
  649.                 first_time = 1;
  650.  
  651.             case BUILTIN_refresh: 
  652.  
  653.                 goto restart;
  654.  
  655.             case '0': case '1': case '2': case '3': case '4': case '5':
  656.             case '6': case '7': case '8': case '9': case 'A': case 'B':
  657.             case 'C': case 'D': case 'E': case 'F': case 'a': case 'b':
  658.             case 'c': case 'd': case 'e': case 'f':
  659.                 if (cnt < 8)
  660.                 {
  661.                     window_cursormove_notify(screen_win, 20,
  662.                                              strlen(seek_txt) + cnt);
  663.                     c = (char)key;
  664.                     window_write(&c, 1);
  665.                     offset[cnt++] = c;
  666.                 }
  667.                 else
  668.                     tty_beep();
  669.                 break;
  670.  
  671.             case BUILTIN_backspace:
  672.  
  673.                 if (cnt)
  674.                     cnt--;
  675.  
  676.                 window_cursormove_notify(screen_win, 20,
  677.                                          strlen(seek_txt) + cnt);
  678.                 window_putch(' ');
  679.                 break;
  680.  
  681.             case BUILTIN_action:
  682.  
  683.                 if (cnt == 0)
  684.                     tty_beep();
  685.                 else
  686.                 {
  687.                     offset[cnt] = 0;
  688.                     sscanf(offset, "%x", &cnt);
  689.                     window_cursormove_notify(screen_win, 20, strlen(seek_txt));
  690.                     window_write("        ", 8);
  691.                     if (cnt < 0)    cnt = 0;
  692.                     if (cnt > size) cnt = size;
  693.                     current_line = cnt >> 4;
  694.                     update_all();
  695.                     cnt = 0;
  696.                 }
  697.                 break;
  698.  
  699.             case BUILTIN_exit:
  700.                 goto end;
  701.  
  702.             default:
  703.                 break;
  704.         }
  705.  
  706.         window_cursormove(screen_win, 20, strlen(seek_txt) + cnt);
  707.     }
  708.  
  709.   end:
  710.     
  711.     clean_up();
  712.     return 0;
  713. }
  714.